unit cx_options_new;

interface
uses
  Windows, Messages, CommCtrl,
  m_api, m_globaldefs, cx_vars, sysutils;

const
  URL_FONTSERVICE = 'http://addons.miranda-im.org/details.php?action=viewfile&id=2065';
  URL_ICOLIB      = 'http://addons.miranda-im.org/details.php?action=viewfile&id=2700';
  URL_EXPLAIN     = 'https://opensvn.csie.org/traccgi/historypp/trac.cgi/wiki/CustomizationSupport';
  URL_NEEDOPTIONS = 'https://opensvn.csie.org/traccgi/historypp/trac.cgi/wiki/AdditionalOptions';

function cx_OnNewOptInit(wParam: WPARAM; lParam: LPARAM): Integer; cdecl;
function cx_NewOptDialogProc(hwndDlg: HWND; uMsg: Integer;
  wParam: WPARAM; lParam: LPARAM): Integer; stdcall;
function cx_VarsDialogProc(hwndDlg: HWND; uMsg: Integer;
  wParam: WPARAM; lParam: LPARAM): Integer; stdcall;

{$include cx_options_new.inc}
{$R 'cx_options_new.res'}

var
  hDlg: HWND = 0;
  hVarsDlg: HWND = 0;

implementation

uses
 Classes,
 dbsettings,
 cx_procs,
 cx_contacts,
 cx_currencies;

var
 cx_opt_Loading: Boolean = false;

function GetEnabled(hDlg: HWND; idCtrl: Integer): Boolean;
begin
 Result := IsWindowEnabled(GetDlgItem(hDlg, idCtrl));
end;

procedure SetEnabled(hDlg: HWND; idCtrl: Integer; Enabled: Boolean);
begin
 EnableWindow(GetDlgItem(hDlg, idCtrl), Enabled);
end;

function GetText(hDlg: HWND; idCtrl: Integer): String;
var
  dlg_text: array[0..1023] of Char;
begin
 ZeroMemory(@dlg_text, SizeOf(dlg_text));
 GetDlgItemText(hDlg, idCtrl, @dlg_text, 1023);
 Result := dlg_text;
end;

procedure SetText(hDlg: HWND; idCtrl: Integer; Text: String);
begin
 SetDlgItemText(hDlg, idCtrl, @Text[1]);
end;

procedure SetChecked(hDlg: HWND; idCtrl: Integer; Checked: Boolean);
begin
 {
 if Checked then
   SendDlgItemMessage(hDlg, idCtrl, BM_SETCHECK, BST_CHECKED, 0)
 else
   SendDlgItemMessage(hDlg, idCtrl, BM_SETCHECK, BST_UNCHECKED, 0);
 }
 if Checked then
   CheckDlgButton(hDlg, idCtrl, BST_CHECKED)
 else
   CheckDlgButton(hDlg, idCtrl, BST_UNCHECKED);
end;

function GetChecked(hDlg: HWND; idCtrl: Integer): Boolean;
begin
 //Result := (SendDlgItemMessage(hDlg, idCtrl, BM_GETCHECK, 0, 0) = BST_CHECKED);
 Result := IsDlgButtonChecked(hDlg, idCtrl)=BST_CHECKED ;
end;

procedure BoxClear(hDlg: HWND; idCtrl: Integer; CB: Boolean = false);
begin
 if CB then
   SendDlgItemMessage(hDlg, idCtrl, CB_RESETCONTENT, 0, 0)
 else
   SendDlgItemMessage(hDlg, idCtrl, LB_RESETCONTENT, 0, 0);
end;

function BoxAdd(hDlg: HWND; idCtrl: Integer; const Text: String; CB: Boolean = false): Integer;
begin
 if CB then
   Result:=SendDlgItemMessage(hDlg, idCtrl, CB_ADDSTRING, 0, DWORD(@Text[1]))
 else
   Result:=SendDlgItemMessage(hDlg, idCtrl, LB_ADDSTRING, 0, DWORD(@Text[1]));
end;

procedure BoxDel(hDlg: HWND; idCtrl, Index: Integer; CB: Boolean = false);
begin
 if CB then
   SendDlgItemMessage(hDlg, idCtrl, CB_DELETESTRING, Index, 0)
 else
   SendDlgItemMessage(hDlg, idCtrl, LB_DELETESTRING, Index, 0);
end;

function BoxCount(hDlg: HWND; idCtrl: Integer; CB: Boolean = false): Integer;
begin
 if CB then
   Result := SendDlgItemMessage(hDlg, idCtrl, CB_GETCOUNT, 0, 0)
 else
   Result := SendDlgItemMessage(hDlg, idCtrl, LB_GETCOUNT, 0, 0);
end;

function BoxGetIndex(hDlg: HWND; idCtrl: Integer; CB: Boolean = false): Integer;
begin
 if CB then
   Result := SendDlgItemMessage(hDlg, idCtrl, CB_GETCURSEL, 0, 0)
 else
   Result := SendDlgItemMessage(hDlg, idCtrl, LB_GETCURSEL, 0, 0);
end;

procedure BoxSetIndex(hDlg: HWND; idCtrl, Index: Integer; CB: Boolean = false);
begin
 if CB then
  begin
   if (Index>=0) and (Index<BoxCount(hDlg, idCtrl, CB)) then
     SendDlgItemMessage(hDlg, idCtrl, CB_SETCURSEL, Index, 0);
  end
 else
  begin
   if (Index>=0) and (Index<BoxCount(hDlg, idCtrl)) then
     SendDlgItemMessage(hDlg, idCtrl, LB_SETCURSEL, Index, 0);
  end;
end;

function BoxIndexOf(hDlg: HWND; idCtrl: Integer; Text: String; CB: Boolean = false): Integer;
begin
 if CB then
   Result:=SendDlgItemMessage(hDlg, idCtrl, CB_FINDSTRING, -1, DWORD(@Text[1]))
 else
   Result:=SendDlgItemMessage(hDlg, idCtrl, LB_FINDSTRING, -1, DWORD(@Text[1]));
end;

procedure BoxAddStrings(hDlg: HWND; idCtrl: Integer; Strings: TStrings; CB: Boolean = false);
 var
  i: Integer;
  Text: String;
begin
 BoxClear(hDlg, idCtrl, CB);
 if Assigned(Strings) then
  begin
   for i:=0 to Strings.Count-1 do
    begin
     Text:=Strings[i];
     if CB then
       SendDlgItemMessage(hDlg, idCtrl, CB_ADDSTRING, 0, DWORD(@Text[1]))
     else
       SendDlgItemMessage(hDlg, idCtrl, LB_ADDSTRING, 0, DWORD(@Text[1]));
    end;
  end;
end;

function BoxGetText(hDlg: HWND; idCtrl: Integer; Index: Integer = 0; CB: Boolean = false): String;
var
  dlg_text: array[0..1023] of Char;
begin
 ZeroMemory(@dlg_text, SizeOf(dlg_text));
 if CB then
   SendDlgItemMessage(hDlg, idCtrl, CB_GETLBTEXT, Index, DWORD(@dlg_text))
 else
   SendDlgItemMessage(hDlg, idCtrl, LB_GETTEXT, Index, DWORD(@dlg_text));
 Result := dlg_text;
end;

procedure UpdateRatesList;
 var
  i: Integer;
begin
  BoxClear(hDlg, CX_IDC_LST);
  for i:=0 to High(cx_Clist) do
   begin
    if cx_Clist[i].Changes=cx_id_Delete then
      BoxAdd(hDlg, CX_IDC_LST, IntToStr(cx_Clist[i].Amount)+' '+cx_Clist[i].Currency+'/'+cx_Clist[i].StateIn+' ('+cx_Clist[i].Source+') ['+Translate(cx_lst_Del)+']')
    else
      BoxAdd(hDlg, CX_IDC_LST, IntToStr(cx_Clist[i].Amount)+' '+cx_Clist[i].Currency+'/'+cx_Clist[i].StateIn+' ('+cx_Clist[i].Source+')');
   end;
end;

procedure SaveChangedOptions;
var
 //ShowRestart: Boolean;
 //Checked: Boolean;
 i: Integer;
begin
 //ShowRestart := False;
 DBWriteContactSettingString(0, piShortName, cx_opt_OptsExist, cx_opt_OptsExist);
 DBWriteContactSettingString(0, piShortName, cx_opt_ContactCaption, PChar(GetText(hDlg, CX_IDC_EDTCC)));
 DBWriteContactSettingString(0, piShortName, cx_opt_StatusMessage, PChar(GetText(hDlg, CX_IDC_EDTSM)));
 DBWriteContactSettingString(0, piShortName, cx_opt_HistoryLog, PChar(GetText(hDlg, CX_IDC_EDTHL)));
 DBWriteContactSettingDWord(0, piShortName, cx_opt_RefreshInterval, StrToIntDef(GetText(hDlg, CX_IDC_EDTRI), IntervalDefault));
 DBWriteContactSettingDWord(0, piShortName, cx_opt_Precision, StrToIntDef(GetText(hDlg, CX_IDC_EDTPR), PrecisionDefault));
 DBWriteContactSettingString(0, piShortName, cx_opt_Unavailable, PChar(GetText(hDlg, CX_IDC_EDTUN)));
 //
 for i:=0 to High(cx_Clist) do
  begin
   (*
   //add new rates
   if cx_Clist[i].hContact=0 then
    begin
     cx_Clist[i].hContact:=cx_AddRate(0, cx_Clist[i].Name, cx_Clist[i].StateIn, cx_Clist[i].Source, cx_Clist[i].Currency, cx_Clist[i].Amount);
    end;
   //delete marked rates
   if cx_Clist[i].ToDelete then
    begin
     {
     if cx_Clist[i].Image<>0 then
      begin
       DestroyIcon(cx_Clist[i].Icon);
       cx_Clist[i].Icon:=0;
      end;
     }
     if cx_Clist[i].hContact<>0 then
       cx_DeleteRate(cx_Clist[i].hContact);
    end;
   *)
   UpdateCurrency(cx_Clist[i]);
  end;
 LoadRates;
 UpdateRatesList;
 //
 cx_UpdateRates;
end;

function AreOptionsChanged: Boolean;
begin
  Result := True;

{  if GetChecked(IDC_SHOWEVENTICONS) <> GridOptions.ShowIcons then exit;
  if GetChecked(IDC_RTLDEFAULT) <> GridOptions.RTLEnabled then exit;
  if GetChecked(IDC_OPENDETAILS) <> GridOptions.OpenDetailsMode then exit;
  if GetChecked(IDC_SHOWEVENTSCOUNT) <> ShowHistoryCount then exit;
  //if GetChecked(IDC_SHOWAVATARS) <> GridOptions.ShowAvatars then exit;

  if GetChecked(IDC_BBCODE) <> GridOptions.BBCodesEnabled then exit;
  if SmileyAddEnabled then
    if GetChecked(IDC_SMILEY) <> GridOptions.SmileysEnabled then exit;
  if MathModuleEnabled then
    if GetChecked(IDC_MATH) <> GridOptions.MathModuleEnabled then exit;
  if GetChecked(IDC_RAWRTF) <> GridOptions.RawRTFEnabled then exit;
  if GetChecked(IDC_AVATARSHISTORY) <> GridOptions.AvatarsHistoryEnabled then exit;

  if GetChecked(IDC_RECENTONTOP) <> GetDBBool(hppDBName,'SortOrder',false) then exit;
  if GetChecked(IDC_GROUPHISTITEMS) <> GetDBBool(hppDBName,'GroupHistoryItems',false) then exit;
}
  {$IFNDEF NO_EXTERNALGRID}
{  if GetChecked(IDC_IEVIEWAPI) <> GetDBBool(hppDBName,'IEViewAPI',false) then exit;
  if GetChecked(IDC_GROUPLOGITEMS) <> GetDBBool(hppDBName,'GroupLogItems',false) then exit;
  if GetChecked(IDC_DISABLEBORDER) <> GetDBBool(hppDBName,'NoLogBorder',false) then exit;
  if GetChecked(IDC_DISABLESCROLL) <> GetDBBool(hppDBName,'NoLogScrollBar',false) then exit;}
  {$ENDIF}

//  Result := False;
end;

function cx_OnNewOptInit(wParam: WPARAM; lParam: LPARAM): Integer; cdecl;
 var
  cx_odp: TOPTIONSDIALOGPAGE;
begin
 ZeroMemory(@cx_odp,SizeOf(TOPTIONSDIALOGPAGE));
 cx_odp.cbSize := sizeof(TOPTIONSDIALOGPAGE);
 cx_odp.Position := 0;
 cx_odp.hInstance := hInstance;
 cx_odp.pszTemplate := MakeIntResource(CX_IDD_OPT);
 cx_odp.szTitle.a := piShortName;
 cx_odp.szGroup.a := 'Plugins';
 cx_odp.pfnDlgProc := @cx_NewOptDialogProc;
 cx_odp.flags := ODPF_BOLDGROUPS;
 PluginLink^.CallService(MS_OPT_ADDPAGE, wParam, DWORD(@cx_odp));
 Result:=0;
end;

// WM_INITDIALOG message handler
function InitDlg: Integer;
 var
  //i: Integer;
  s: String;
  sl: TStrings;
begin
  //ShowWindow(GetDlgItem(hDlg,CX_ID_LOOK_FONT_LINK),SW_HIDE);

  cx_opt_Loading:=true;
  //display options
  s:=DBReadString(0, piShortName, cx_opt_ContactCaption);
  if s='' then
    s:=cx_ContactCaptionDef;
  SetText(hDlg, CX_IDC_EDTCC, s);
  SetText(hDlg, CX_IDC_EXCC, cx_FormatString(s));
  s:=DBReadString(0, piShortName, cx_opt_StatusMessage);
  if s='' then
    s:=cx_StatusMessageDef;
  SetText(hDlg, CX_IDC_EDTSM, s);
  SetText(hDlg, CX_IDC_EXSM, cx_FormatString(s));
  s:=DBReadString(0, piShortName, cx_opt_HistoryLog);
  if s='' then
    s:=cx_HistoryLogDef;
  SetText(hDlg, CX_IDC_EDTHL, s);
  SetText(hDlg, CX_IDC_EXHL, cx_FormatString(s));
  s:=IntToStr(DBGetContactSettingDword(0, piShortName, cx_opt_RefreshInterval, IntervalDefault));
  SetText(hDlg, CX_IDC_EDTRI, s);
  s:=IntToStr(DBGetContactSettingDword(0, piShortName, cx_opt_Precision, PrecisionDefault));
  SetText(hDlg, CX_IDC_EDTPR, s);
  s:=DBReadString(0, piShortName, cx_opt_Unavailable);
  if s='' then
    s:=UnavailableDef;
  SetText(hDlg, CX_IDC_EDTUN, s);
  //rates list
  LoadRates;
  UpdateRatesList;
  //currency list
  sl:=TStringList.Create;
  {
  sl.Add('BYR');
  sl.Add('RUR');
  sl.Add('USD');
  BoxClear(hDlg, CX_IDC_CBFROM, true);
  BoxAddStrings(hDlg, CX_IDC_CBFROM, sl, true);
  if BoxCount(hDlg, CX_IDC_CBFROM, true)>0 then
    BoxSetIndex(hDlg, CX_IDC_CBFROM, 0, true);
  BoxClear(hDlg, CX_IDC_CBTO, true);
  BoxAddStrings(hDlg, CX_IDC_CBTO, sl, true);
  if BoxCount(hDlg, CX_IDC_CBTO, true)>0 then
    BoxSetIndex(hDlg, CX_IDC_CBTO, 0, true);
  }
  BoxClear(hDlg, CX_IDC_CBFROM, true);
  BoxAddStrings(hDlg, CX_IDC_CBFROM, cx_currcode, true);
  if BoxCount(hDlg, CX_IDC_CBFROM, true)>0 then
    BoxSetIndex(hDlg, CX_IDC_CBFROM, 0, true);
  BoxClear(hDlg, CX_IDC_CBTO, true);
  BoxAddStrings(hDlg, CX_IDC_CBTO, cx_currcode, true);
  if BoxCount(hDlg, CX_IDC_CBTO, true)>0 then
    BoxSetIndex(hDlg, CX_IDC_CBTO, 0, true);
  //source list
  sl.Clear;
  sl.Add('Google');
  sl.Add('cbr.ru');
  sl.Add('nbrb.by');
  BoxClear(hDlg, CX_IDC_CBSRC, true);
  BoxAddStrings(hDlg, CX_IDC_CBSRC, sl, true);
  if BoxCount(hDlg, CX_IDC_CBSRC, true)>0 then
    BoxSetIndex(hDlg, CX_IDC_CBSRC, 0, true);
  sl.Free;
  //
  SetText(hDlg, CX_IDC_EDTAMT, '1');
  //
  SetText(hDlg, CX_IDC_EDTCCC, '');
  SetText(hDlg, CX_IDC_EDTCSM, '');
  //
  cx_opt_Loading:=false;
  //
  Result := 0;
end;

function CommandDlg(idCtrl: Integer; hCtrl: HWND; wNotifyCode: Integer): Integer;
 var
  s: String;
  i, i_f, i_t, i_s, t: Integer;
 //
 function IsDifferent: Boolean;
 begin
  Result:=false;
  if cx_opt_Loading
    then Exit;
  i:=LB_ERR;
  i:=BoxGetIndex(hDlg, CX_IDC_LST);
  if (i>=0) and (Length(cx_CList)>i) then
   begin
    i_f:=BoxGetIndex(hDlg, CX_IDC_CBFROM, true);
    s:=BoxGetText(hDlg, CX_IDC_CBFROM, i_f, true);
    try
     Result:=Result or (s<>cx_CList[i].Currency);
    except
     MessageBox(hDlg, PChar('cx_Clist index error: '+IntToStr(i)), piShortName, MB_OK or MB_ICONERROR);
    end;
    i_t:=BoxGetIndex(hDlg, CX_IDC_CBTO, true);
    s:=BoxGetText(hDlg, CX_IDC_CBTO, i_t, true);
    try
     Result:=Result or (s<>cx_CList[i].StateIn);
    except
     MessageBox(hDlg, 'cx_Clist index error!', piShortName, MB_OK or MB_ICONERROR);
    end;
    i_s:=BoxGetIndex(hDlg, CX_IDC_CBSRC, true);
    s:=BoxGetText(hDlg, CX_IDC_CBSRC, i_s, true);
    try
     Result:=Result or (s<>cx_CList[i].Currency);
    except
     MessageBox(hDlg, 'cx_Clist index error!', piShortName, MB_OK or MB_ICONERROR);
    end;
    t:=Abs(StrToIntDef(GetText(hDlg, CX_IDC_EDTAMT), 1));
    try
     Result:=Result or (t<>cx_CList[i].Amount);
    except
     MessageBox(hDlg, 'cx_Clist index error!', piShortName, MB_OK or MB_ICONERROR);
    end;
    //0.3.0.6
    s:=GetText(hDlg, CX_IDC_EDTCCC);
    try
     Result:=Result or (s<>cx_CList[i].CC);
    except
     MessageBox(hDlg, 'cx_Clist index error!', piShortName, MB_OK or MB_ICONERROR);
    end;
    s:=GetText(hDlg, CX_IDC_EDTCSM);
    try
     Result:=Result or (s<>cx_CList[i].SM);
    except
     MessageBox(hDlg, 'cx_Clist index error!', piShortName, MB_OK or MB_ICONERROR);
    end;
   end;
 end;
begin
  Result := 0;
  case idCtrl of
   //208:           ShowXCHForm;
   CX_IDC_BTNNEW:
    begin
     i_f:=BoxGetIndex(hDlg, CX_IDC_CBFROM, true);
     i_t:=BoxGetIndex(hDlg, CX_IDC_CBTO, true);
     i_s:=BoxGetIndex(hDlg, CX_IDC_CBSRC, true);
     i:=cx_FindRate(BoxGetText(hDlg, CX_IDC_CBFROM, i_f, true), BoxGetText(hDlg, CX_IDC_CBTO, i_t, true), BoxGetText(hDlg, CX_IDC_CBSRC, i_s, true), Abs(StrToIntDef(GetText(hDlg, CX_IDC_EDTAMT), 1)));
     if i<0 then
      begin
       if i_f=i_t then
         MessageBox(hDlg, Translate(cx_err_NoSame), Translate(cx_dlg_NewCaption), MB_OK or MB_ICONERROR)
       else
        begin
         //cx_AddRate(0, '', BoxGetText(CX_IDC_CBTO, i_f, true), BoxGetText(CX_IDC_CBSRC, i_t, true), BoxGetText(CX_IDC_CBFROM, i_s, true), 1);
         //LoadRates;
         i:=AddNewRateToCList;
         cx_CList[i].Source:=BoxGetText(hDlg, CX_IDC_CBSRC, i_s, true);
         cx_CList[i].StateIn:=BoxGetText(hDlg, CX_IDC_CBTO, i_t, true);
         cx_CList[i].Amount:=Abs(StrToIntDef(GetText(hDlg, CX_IDC_EDTAMT), 1));
         cx_CList[i].Currency:=BoxGetText(hDlg, CX_IDC_CBFROM, i_f, true);
         cx_CList[i].Name:=cx_CList[i].Currency+'/'+cx_CList[i].StateIn;
         cx_CList[i].CurrentRate:='0';
         cx_CList[i].hContact:=0;
         cx_CList[i].Changes:=cx_id_All;
         //0.3.0.6
         cx_CList[i].CC:='';
         cx_CList[i].SM:='';
         //
         UpdateRatesList;
         //
         SetText(hDlg, CX_IDC_EDTAMT, '1');
        end;
      end
     else
      begin
       BoxSetIndex(hDlg, CX_IDC_LST, i);
       if cx_Clist[i].Changes=cx_id_Delete then //has marked rate
        begin
         //unmark rate
         cx_Clist[i].Changes:=0;
         UpdateRatesList;
        end
       else
         MessageBox(hDlg, Translate(cx_err_Exists), Translate(cx_dlg_NewCaption), MB_OK or MB_ICONERROR);
      end;
     Result:=1;
    end;
   CX_IDC_BTNDEL:
    begin
     i:=BoxGetIndex(hDlg, CX_IDC_LST);
     if i>=0 then
      begin
       s:=Translate(cx_dlg_DeleteSure);
       if MessageBox(hDlg, PChar(Format(s, [cx_Clist[i].Currency,cx_Clist[i].StateIn,cx_Clist[i].Source])), Translate(cx_dlg_DeleteCaption), MB_YESNO or MB_DEFBUTTON2 or MB_ICONQUESTION)=IDYES then
        begin
         //mark rate to delete
         cx_Clist[i].Changes:=cx_id_Delete;
         UpdateRatesList;
        end;
       Result:=1;
      end;
    end;
   CX_IDC_BTNVAR:
    begin
     CreateDialog(hInstance, MakeIntResource(CX_IDD_VARS), hDlg, @cx_VarsDialogProc);
    end;
   CX_IDC_CBFROM, CX_IDC_CBTO, CX_IDC_CBSRC:
    begin
     if not cx_opt_Loading then
      begin
       if wNotifyCode = CBN_SELCHANGE then
        begin
         SetEnabled(hDlg, CX_IDC_BTNCHN, IsDifferent);
        end;
      end;
    end;
   CX_IDC_EDTAMT:
    begin
     if not cx_opt_Loading then
      begin
       if wNotifyCode = EN_CHANGE then
         SetEnabled(hDlg, CX_IDC_BTNCHN, IsDifferent);
      end;
    end;
   CX_IDC_BTNCHN:
    begin
     i_f:=BoxGetIndex(hDlg, CX_IDC_CBFROM, true);
     i_t:=BoxGetIndex(hDlg, CX_IDC_CBTO, true);
     i_s:=BoxGetIndex(hDlg, CX_IDC_CBSRC, true);
     i:=cx_FindRate(BoxGetText(hDlg, CX_IDC_CBFROM, i_f, true), BoxGetText(hDlg, CX_IDC_CBTO, i_t, true), BoxGetText(hDlg, CX_IDC_CBSRC, i_s, true), Abs(StrToIntDef(GetText(hDlg, CX_IDC_EDTAMT), 1)));
     if i<0 then
      begin
         i:=BoxGetIndex(hDlg, CX_IDC_LST);
         cx_CList[i].Source:=BoxGetText(hDlg, CX_IDC_CBSRC, i_s, true);
         cx_CList[i].StateIn:=BoxGetText(hDlg, CX_IDC_CBTO, i_t, true);
         cx_CList[i].Amount:=Abs(StrToIntDef(GetText(hDlg, CX_IDC_EDTAMT), 1));
         cx_CList[i].Currency:=BoxGetText(hDlg, CX_IDC_CBFROM, i_f, true);
         cx_CList[i].Name:=cx_CList[i].Currency+'/'+cx_CList[i].StateIn;
         //0.3.0.6
         cx_CList[i].CC:=GetText(hDlg, CX_IDC_EDTCCC);
         cx_CList[i].SM:=GetText(hDlg, CX_IDC_EDTCSM);
         //
         cx_CList[i].Changes:=cx_id_Name or cx_id_Amount or cx_id_Currency or cx_id_StateIn or cx_id_Source or cx_id_CC or cx_id_SM;
         //
         UpdateRatesList;
         //
         SetText(hDlg, CX_IDC_EDTAMT, '1');
         //
       SetEnabled(hDlg, CX_IDC_BTNCHN, IsDifferent);
       //
       Result:=1;
      end
     else
      begin
       //0.3.0.6
       if (GetText(hDlg, CX_IDC_EDTCCC)<>cx_CList[i].CC) or (GetText(hDlg, CX_IDC_EDTCSM)<>cx_CList[i].SM) then
        begin
         cx_CList[i].CC:=GetText(hDlg, CX_IDC_EDTCCC);
         cx_CList[i].SM:=GetText(hDlg, CX_IDC_EDTCSM);
         cx_CList[i].Changes:=cx_id_CC or cx_id_SM;
         //
         UpdateRatesList;
         //
         SetText(hDlg, CX_IDC_EDTAMT, '1');
         //
         SetEnabled(hDlg, CX_IDC_BTNCHN, IsDifferent);
         //
         Result:=1;
        end
       else
        begin
         BoxSetIndex(hDlg, CX_IDC_LST, i);
         MessageBox(hDlg, Translate(cx_err_Exists), Translate(cx_dlg_ChangeCaption), MB_OK or MB_ICONERROR);
        end;
      end;
    end;
   CX_IDC_EDTCC:
    begin
     if wNotifyCode = EN_CHANGE then
      begin
       s:=GetText(hDlg, CX_IDC_EDTCC);
       SetText(hDlg, CX_IDC_EXCC, cx_FormatString(s));
       Result:=1;
      end;
    end;
   CX_IDC_EDTSM:
    begin
     if wNotifyCode = EN_CHANGE then
      begin
       s:=GetText(hDlg, CX_IDC_EDTSM);
       SetText(hDlg, CX_IDC_EXSM, cx_FormatString(s));
       Result:=1;
      end;
    end;
   CX_IDC_EDTHL:
    begin
     if wNotifyCode = EN_CHANGE then
      begin
       s:=GetText(hDlg, CX_IDC_EDTHL);
       SetText(hDlg, CX_IDC_EXHL, cx_FormatString(s));
       Result:=1;
      end;
    end;
   CX_IDC_EDTUN:
    begin
     if wNotifyCode = EN_CHANGE then
       Result:=1;
    end;
   CX_IDC_LST:
    begin
     if not cx_opt_Loading then
      begin
       case wNotifyCode of
        LBN_SELCHANGE:
         begin
          i:=BoxGetIndex(hDlg, CX_IDC_LST);
          SetEnabled(hDlg, CX_IDC_BTNDEL, i>=0);
          SetEnabled(hDlg, CX_IDC_BTNCHN, false);
          if i>=0 then
           begin
            i_f:=BoxIndexOf(hDlg, CX_IDC_CBFROM, cx_CList[i].Currency, true);
            BoxSetIndex(hDlg, CX_IDC_CBFROM, i_f, true);
            i_t:=BoxIndexOf(hDlg, CX_IDC_CBTO, cx_CList[i].StateIn, true);
            BoxSetIndex(hDlg, CX_IDC_CBTO, i_t, true);
            i_s:=BoxIndexOf(hDlg, CX_IDC_CBSRC, cx_CList[i].Source, true);
            BoxSetIndex(hDlg, CX_IDC_CBSRC, i_s, true);
            cx_opt_Loading:=true;
            SetText(hDlg, CX_IDC_EDTAMT, IntToStr(cx_CList[i].Amount));
            //0.3.0.6
            SetText(hDlg, CX_IDC_EDTCCC, cx_CList[i].CC);
            SetText(hDlg, CX_IDC_EDTCSM, cx_CList[i].SM);
            //
            cx_opt_Loading:=false;
           end;
         end;
        end;
       //Result:=1;
      end;
    end;
   //0.3.0.6
   CX_IDC_BTNGDM:
    begin
     SetText(hDlg, CX_IDC_EDTCCC, '');
     SetText(hDlg, CX_IDC_EDTCSM, '');
    end;
   CX_IDC_EDTCCC:
    begin
     if wNotifyCode = EN_CHANGE then
      begin
       SetEnabled(hDlg, CX_IDC_BTNCHN, IsDifferent);
       Result:=1;
      end;
    end;
   CX_IDC_EDTCSM:
    begin
     if wNotifyCode = EN_CHANGE then
      begin
       SetEnabled(hDlg, CX_IDC_BTNCHN, IsDifferent);
       Result:=1;
      end;
    end;
   else
    Result := 0;
   end;
  if Result=1 then
   begin
    if AreOptionsChanged then
      SendMessage(GetParent(hDlg), PSM_CHANGED, hDlg, 0);
   end;
end;

// WM_NOTIFY message handler
function NotifyDlg(idCtrl: Integer; nmhdr: TNMHDR): Integer;
begin
  Result := 0;
  if nmhdr.code <> PSN_APPLY then exit;
  Result := 1;
  // apply changes here
  SaveChangedOptions;
end;

function cx_NewOptDialogProc(hwndDlg: HWND; uMsg: Integer;
  wParam: WPARAM; lParam: LPARAM): Integer;
begin
  Result := 0;
  case uMsg of
    WM_INITDIALOG: begin hDlg := hwndDlg; TranslateDialogDefault(hwndDlg); Result := InitDlg; end;
    WM_NOTIFY:     Result := NotifyDlg(wParam,PNMHDR(lParam)^);
    WM_COMMAND:    Result := CommandDlg(LoWord(wParam),lParam,HiWord(wParam));
    WM_DESTROY:    hDlg := 0;
  end;
end;


function InitVarsDlg: Integer;
begin
 SetText(hVarsDlg, CX_IDC_STCFROM, cx_txt_sc);
 SetText(hVarsDlg, CX_IDC_STCTO, cx_txt_dc);
 SetText(hVarsDlg, CX_IDC_STCRATE, cx_txt_cr);
 SetText(hVarsDlg, CX_IDC_STCPREV, cx_txt_pr);
 SetText(hVarsDlg, CX_IDC_STCNEXT, cx_txt_ur);
 SetText(hVarsDlg, CX_IDC_STCDATE, cx_txt_dt);
 SetText(hVarsDlg, CX_IDC_STCSRC, cx_txt_rs);
 SetText(hVarsDlg, CX_IDC_STCAMT, cx_txt_am);
 SetText(hVarsDlg, CX_IDC_STCRATEAMT, cx_txt_cra);
 SetText(hVarsDlg, CX_IDC_STCPREVAMT, cx_txt_pra);
 SetText(hVarsDlg, CX_IDC_STCNEXTAMT, cx_txt_ura);
 //
 Result:=0;
end;

function cx_VarsDialogProc(hwndDlg: HWND; uMsg: Integer;
  wParam: WPARAM; lParam: LPARAM): Integer;
begin
  Result := 0;
  case uMsg of
    WM_INITDIALOG: begin hVarsDlg := hwndDlg; InitVarsDlg; TranslateDialogDefault(hwndDlg); end;
    WM_COMMAND:    DestroyWindow(hVarsDlg);
    WM_DESTROY:    hVarsDlg := 0;
  end;
end;

end.
